package Simulator;

import EcoSpeed.Utils;

/**
 * Class DriverLift
 * Driver pour un ascenseur simulé.
 * Un thread par ascenseur.
 */
public class DriverLift extends EcoSpeed.DriverLift {

    /**
     * Etage actuelle de l'ascenseur
     */
    private int currentFloor = EcoSpeed.Utils.NB_UNDERGROUND;
    /**
     * Etage de destination de l'ascenseur
     */
    private int targetFloor = EcoSpeed.Utils.NB_UNDERGROUND;
    /**
     * Etat de la porte
     */
    private boolean doorOpen = false;
    /**
     * Si l'ascenseur vien de s'arreté
     */
    private boolean stop = true;
    /**
     * Identifiant de l'ascenseur
     */
    private int id;
    /**
     * Charge actuel de l'ascenseur
     */
    private int weight = 0;
    /**
     * Charge maximum possible pour un ascenseur
     */
    public static int maxWeight = 1000;

    /**
     * Constructeur
     * @param id Identifiant de l'ascenseur
     */
    public DriverLift(int id) {
        this.id = id;
    }

    /**
     * Modifie la charge
     * @param weight nouvelle charge
     * @return true si le chagement s'est effectué, false si non
     */
    public boolean setWeight(int weight) {
        if (weight <= DriverLift.maxWeight) {
            this.weight = weight;
            return true;
        }
        return false;
    }

    /**
     * Ascesseur de l'étage de destination
     * @return l'étage de destination
     */
    public int getTargetFloor() {
        return targetFloor;
    }

    /**
     * Methode apeller par @EcoSpeed.TimeLine pour le depalcement des ascenseurs
     */
    public void update() {
        if (this.doorOpen) {
            this.closeDoor();
            this.setChanged();
            this.notifyObservers(0);
        } else {
            if (this.currentFloor < this.targetFloor) {
                this.currentFloor++;
                this.setChanged();
                this.notifyObservers(1);
            } else if (this.currentFloor > this.targetFloor) {
                this.currentFloor--;
                this.setChanged();
                this.notifyObservers(-1);
            }
            if (!this.stop && this.currentFloor == this.targetFloor) {
                this.stop = true;
                this.openDoor();
                this.setChanged();
                this.notifyObservers(0);
            }
        }
    }

    /**
     * Ascesseur de l'étage actuel
     * @return l'étage actuel
     */
    @Override
    public int getFloor() {
        return this.currentFloor;
    }

    /**
     * Donne la charge actuelle
     * @return la charge
     */
    @Override
    public int getWeight() {
        return this.weight;
    }

    /**
     * Donne la charge maximum
     * @return la charge maximum
     */
    @Override
    public int getMaxWeight() {
        return DriverLift.maxWeight;
    }

    /**
     * Modifie l'étage de destination
     * @param floor la nouvelle destination
     */
    @Override
    public void moveTo(int floor) {
        this.stop = false;
        this.targetFloor = floor;
    }

    /**
     * Ouvre la porte
     */
    @Override
    public void openDoor() {
        this.doorOpen = true;
    }

    /**
     * Ferme la porte
     */
    @Override
    public void closeDoor() {
        this.doorOpen = false;
    }

    /**
     * Savoir si l'ascenseur a ses portes ouvertent ou non
     * @return true si les portes sont ouvertent, false si non
     */
    @Override
    public boolean doorOpened() {
        return this.doorOpen;
    }

    /**
     * Ascesseur de l'identifiant
     * @return l'identifiant
     */
    @Override
    public int getId() {
        return this.id;
    }

    /**
     * Modifie l'étage actuel
     * @param val nouvelle valeur
     */
    @Override
    public void setFloor(int val) {
        this.currentFloor = val;
        this.setChanged();
        this.notifyObservers(0);
    }

    /**
     * Reinitialise l'ascenseur
     */
    @Override
    public void reset() {
        this.currentFloor = Utils.NB_UNDERGROUND;
        this.doorOpen = false;
        this.targetFloor = Utils.NB_UNDERGROUND;
        this.weight = 0;
        this.stop = true;
        this.setChanged();
        this.notifyObservers(0);
    }
}
